package cn.iocoder.boot.springai001.service;

import org.springframework.stereotype.Component;

/**
 * 提示词模板管理器
 * <p>
 * 统一管理系统中所有提示词模板，提供统一的提示词构建和管理方法
 * <p>
 * 核心功能：
 * 1. **思维链（CoT）**：通过 Zero-shot 或 Few-shot 模式引导模型逐步推理
 * 2. **任务规划**：提供系统级提示词，定义 AI 角色、工具使用、执行规范
 * <p>
 * 组合使用策略：
 * - 任务规划 + CoT：适用于复杂任务的分解执行 + 增强推理能力
 * - 单独 CoT：适用于简单问答的场景，提升推理准确性
 * - 单独任务规划：适用于不需要推理引导的标准化流程
 * <p>
 * 示例用法：
 * <pre>
 * // 任务规划 + CoT 组合使用
 * String systemPrompt = promptTemplateManager.buildTaskPlanningPrompt(true);
 * String userQuery = promptTemplateManager.processChainOfThought(
 *     "查询昨天的效能数据并分析",
 *     true, "ZERO_SHOT", null
 * );
 * </pre>
 */
@Component
public class PromptTemplateManager {

    /**
     * 处理思维链（Chain of Thought）模式
     *
     * @param query      原始用户问题
     * @param enableCoT  是否启用CoT
     * @param cotMode    CoT模式类型
     * @param cotExample CoT示例（Few-shot模式使用）
     * @return 处理后的问题文本
     */
    public String processChainOfThought(String query, Boolean enableCoT, String cotMode, String cotExample) {
        // 如果未启用CoT，直接返回原始问题
        if (enableCoT == null || !enableCoT) {
            return query;
        }

        // 判断CoT模式类型
        if ("FEW_SHOT".equalsIgnoreCase(cotMode)) {
            // Few-shot CoT：提供示例 + 当前问题
            return buildFewShotCoT(query, cotExample);
        } else {
            // Zero-shot CoT（默认）：在问题后添加引导语
            return buildZeroShotCoT(query);
        }
    }

    /**
     * 构建 Zero-shot CoT 提示
     * <p>
     * 在问题后添加 "让我们逐步思考" 来触发模型的逐步推理
     */
    private String buildZeroShotCoT(String query) {
        return query + "\n\n让我们逐步思考。";
    }

    /**
     * 构建 Few-shot CoT 提示
     * <p>
     * 提供示例问题和推理过程，然后提出当前问题
     */
    private String buildFewShotCoT(String query, String cotExample) {
        StringBuilder prompt = new StringBuilder();

        // 如果有自定义示例，使用自定义示例
        if (cotExample != null && !cotExample.trim().isEmpty()) {
            prompt.append(cotExample).append("\n\n");
        } else {
            // 使用默认示例
            prompt.append("Q: 当我兄弟2岁时，我的年龄是他的2倍。现在我40岁了，我兄弟多大？让我们逐步思考。\n");
            prompt.append("A: 当我兄弟2岁时，我是 2 × 2 = 4岁。这意味着我们的年龄差是2岁，而且我更大。");
            prompt.append("现在我40岁了，所以我兄弟是 40 - 2 = 38岁。答案是38岁。\n\n");
        }

        // 添加当前问题
        prompt.append("Q: ").append(query).append(" 让我们逐步思考。\n");
        prompt.append("A: ");

        return prompt.toString();
    }

    /**
     * 构建任务规划系统提示词
     *
     * @param showToolResults 是否显示工具执行结果
     * @return 系统提示词
     */
    public String buildTaskPlanningPrompt(Boolean showToolResults) {
        StringBuilder prompt = new StringBuilder();

        prompt.append("你是一个专业的任务规划助手，擅长将复杂任务分解为多个步骤，并按逻辑顺序执行。\n\n");

        prompt.append("你的核心能力：\n");
        prompt.append("1. **任务分解**：将复杂问题分解为清晰的步骤\n");
        prompt.append("2. **工具选择**：根据任务需要选择合适的工具\n");
        prompt.append("3. **逻辑推理**：基于中间结果进行逻辑推理和决策\n");
        prompt.append("4. **结果整合**：将多个步骤的结果整合为最终结论\n\n");

        appendAvailableTools(prompt);

        appendExecutionRules(prompt);

        appendExecutionRulesPart2(prompt);

        if (showToolResults) {
            appendToolExecutionDisplayRequirements(prompt);
        }

        prompt.append("请根据用户的问题，制定详细的执行计划并逐步执行，无需人工确认。若未实际完成工具调用，不得输出'工具返回结果：待返回...'或任何虚拟结果描述。");

        return prompt.toString();
    }

    /**
     * 添加可用工具描述
     */
    private void appendAvailableTools(StringBuilder prompt) {
        prompt.append("可用工具（必须以函数调用形式真实调用，禁止仅叙述）：\n");
        prompt.append("- DateTimeTools.getCurrentDateTime()：获取当前时间（ISO-8601，含时区），用于计算特定日期\n");
        prompt.append("- ExecuteSqlTools.executeSql()：执行SQL工具 \n");

        prompt.append("- MCP 服务器（动态工具）：通过 MCP 协议提供动态工具集，包括但不限于：\n");
        prompt.append("  • springai001-api-server：getCountySuperviseUsingPOST(dataDay, organId, pageNum, pageSize)：查询区县级效能指数\n");
        prompt.append("  • springai001-api-server：getTownSuperviseUsingPOST(dataDay, organId, pageNum, pageSize)：查询镇街级效能指数\n");
        prompt.append("  • springai001-api-server：getVillageSuperviseUsingPOST(dataDay, organId, pageNum, pageSize)：查询村社级效能指数\n");
        prompt.append("  • mcp-server-chart：图表生成工具，支持柱状图、饼图、折线图、雷达图、桑基图等 15+ 种图表类型\n");
        prompt.append("  • mcp-server-fetch：HTTP 请求调用\n\n");
    }

    /**
     * 添加严格执行规范
     */
    private void appendExecutionRules(StringBuilder prompt) {
        prompt.append("严格执行规范：\n");
        prompt.append("1. 如需时间或任何外部数据，必须通过上述工具进行函数调用；不得凭空编造，也不得只写'正在调用'或'待返回...'之类的叙述。\n");
        prompt.append("2. 只有在收到工具真实返回后，才可以展示结果与分析；如果工具报错或不可用，需明确说明错误并提出可行替代方案。\n");
        prompt.append("3. 优先顺序：先用 DateTimeTools 计算所需日期，再调用相应 ApiTools 获取数据，然后进行比较/定位/下钻分析。\n");
        prompt.append("4. 参数要求：\n");
        prompt.append("   - dataDay：yyyy-MM-dd（若为空，后端将按默认规则处理；建议显式传入）。\n");
        prompt.append("   - organId：默认3306（全域或上级组织ID），下钻时传入目标区域的 organId。\n");
        prompt.append("   - pageNum：默认1；pageSize：县级10、镇级/村级100。\n");
        prompt.append("5. 禁止使用臆测数据、示例数据或占位符（如\"最差区域的ID\"）；必须以工具返回中的真实 organId 继续下钻。\n\n");
    }

    /**
     * 添加执行原则
     */
    private void appendExecutionRulesPart2(StringBuilder prompt) {
        prompt.append("执行原则：\n");
        prompt.append("1. 先获取必要的时间信息（如需要特定日期）\n");
        prompt.append("2. 按逻辑顺序调用相关工具获取数据\n");
        prompt.append("3. 对每次获取的数据进行分析和推理\n");
        prompt.append("4. 基于分析结果决定下一步行动\n");
        prompt.append("5. 如需可视化，使用 mcp-server-chart 生成图表（支持柱状图、饼图、折线图等）\n");
        prompt.append("6. 最终整合所有信息得出结论\n\n");
    }

    /**
     * 添加工具执行结果显示要求
     */
    private void appendToolExecutionDisplayRequirements(StringBuilder prompt) {
        prompt.append("**重要：工具执行结果显示要求**\n");
        prompt.append("在调用每个工具后，请务必：\n");
        prompt.append("1. 明确说明你正在调用哪个工具\n");
        prompt.append("2. 显示工具调用的参数\n");
        prompt.append("3. 完整展示工具返回的原始结果\n");
        prompt.append("4. 对工具结果进行简要分析和解释\n");
        prompt.append("5. 基于工具结果决定下一步行动\n\n");
        
        appendExampleFormat(prompt);
    }

    /**
     * 添加格式示例
     */
    private void appendExampleFormat(StringBuilder prompt) {
        prompt.append("格式示例：\n");
        prompt.append("```\n");
        prompt.append("🔧 正在调用工具：ApiTools.getCountySupervise\n");
        prompt.append("📥 参数：{ dataDay: \"2024-01-14\", organId: \"3306\", pageNum: 1, pageSize: 10 }\n");
        prompt.append("📊 工具原始返回：<完整JSON>\n");
        prompt.append("💡 分析：基于返回字段（如 totalGrade、organId 等）进行比较与判断\n");
        prompt.append("➡️ 下一步：基于真实 organId 下钻调用 ApiTools.getTownSupervise\n");
        prompt.append("```\n\n");
    }
}

